
//
// 120720 - AH - (Kryddar) Created.
// 130404 - AH - (Midtun *) getBisonCount().
// 130617 - AH - (Dampen) data renamed location.
// 130703 - AH - (Midtun *) getMime(), getScheme(), getUri(), getTail(),
//               getTailEncoded() and parsedToString(). 
//

package org.soekrat.engine.socraton;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

import org.japril.jutil.CharArrayPrintWriter;

/**
 * <p>
 *   Bison is a sign showing the presence of an information.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC)
 */
public class Bison implements BisonSource
{
  private final String m_location;
  
  /**
   * <p>
   *  Constructor.
   * </p>
   * @param location Data.
   */
  public Bison(String location)
  {
    if (location==null)
    {
      throw new NullPointerException("location");
    }
    
    location=location.trim();
    if (location.length()==0)
    {
      throw new IllegalArgumentException("location the empty string");
    }
    
    m_location=location;
  }
  
  // Specified in BisonSource.
  public final int getBisonCount(){ return 1; }

  // Specified in BisonSource.
  public final List<Bison> getBisons(){ return getBisons(null); }

  // Specified in BisonSource.
  public final List<Bison> getBisons(List<Bison> bisons)
  {
    bisons=(bisons==null) ? new ArrayList<Bison>() : bisons;
    bisons.add(this);
    return bisons;
  }

  /**
   * <p>
   *   Gets location.
   * </p>
   * @return Location.
   */
  public final String getLocation(){ return m_location; }
  
  @Override
  public final boolean equals(Object o)
  {
    if (o==this) return true;
    if (!(o instanceof Bison)) return false;
    return ((Bison)o).m_location.equals(m_location);
  }

  @Override
  public final int hashCode(){ return m_location.hashCode(); }

  @Override
  public final String toString(){ return getLocation(); }
  
  /**
   * <p>
   *   The empty array shared. 
   * </p>
   */
  public static final Bison[] EMPTY_ARRAY=new Bison[0];
  
  //
  
  private String m_mime=null;
  
  private String m_scheme=null;
  
  private String m_uri=null;
  
  private String m_tail=null;
  
  private void parse()
  {
    if (m_uri==null) // Always has tail so can use to check not done parsing.
    {
      int idx0=m_location.indexOf(':');
      if (idx0==-1)
      {
        m_uri=m_tail=m_location;
        return;
      }
      
      int idx1=m_location.indexOf(':', idx0+1);
      
      if (idx1==-1)
      {
        m_scheme=m_location.substring(0, idx0);
        m_uri=m_location;
        m_tail=m_location.substring(idx1+1);
      }
      else
      {
        m_mime=m_location.substring(0, idx0);
        m_scheme=m_location.substring(idx0+1, idx1);
        m_uri=m_location.substring(idx0+1);
        m_tail=m_location.substring(idx1+1);
      }
    }
  }
  
  /**
   * <p>
   *   Gets mime type part of bison's location.
   * </p>
   * @return mime type or {@code null} if not have.
   */
  public final String getMime(){ parse(); return m_mime; }
  
  /**
   * <p>
   *   Gets scheme part of bison location's URI. 
   * </p>
   * @return Scheme.
   */
  public final String getScheme(){ parse(); return m_scheme; }
  
  /**
   * <p>
   *   Gets URI of bison location.
   * </p>
   * @return URI string presentation.
   */
  public final String getUri(){ parse(); return m_uri; }
  
  /**
   * <p>
   *   Gets part of bison data after scheme.
   * </p>
   * @return Tail.
   */
  public final String getTail(){ parse(); return m_tail; }
  
  /**
   * <p>
   *   Gets 
   *   {@link #getTail() tail} decoded.
   * </p>
   * @return Tail decoded.
   */
  public final String getTailDecoded()
  {
    try
    {
      return URLDecoder.decode(getTail(), "ISO-8859-1");
    }
    catch (UnsupportedEncodingException uex)
    {
      return getTail();
    }
  }
  
  /**
   * <p>
   *   Gets string of bison data parsed components for demo and test purposes.
   * </p>
   * @return String with parsed components.
   */
  public final String parsedToString()
  {
    CharArrayPrintWriter cawp=new CharArrayPrintWriter();
    String mime=getMime();
    if (mime!=null) cawp.println("  mime: "+mime);
    cawp.println("  scheme="+getScheme());
    cawp.println("  uri="+getUri());
    cawp.println("  tail="+getTail());
    cawp.println("  tail-decoded=="+getTailDecoded());
    return cawp.toString();
  }
  
  public static void main(String[] args)
  {
    Bison b0=new Bison("image/jpg:http://farm3.staticflickr.com/2806/9169999754_bc95260939_b.jpg");
    System.out.println(b0);
    System.out.println(b0.parsedToString());
    
    System.out.println();
    System.out.println();
    
    Bison b1=new Bison("text/plain:this:%5bmulti%5darne+likes+beer");
    System.out.println(b1);
    System.out.println(b1.parsedToString());
  }
  
}
